void ClientSideEncryption::setCertificate(const QSslCertificate &certificate)
{
- _encryptionCertificate = CertificateInformation{_encryptionCertificate.getPrivateKeyData(), QSslCertificate{certificate}};
+ _encryptionCertificate = CertificateInformation{useTokenBasedEncryption() ? CertificateInformation::CertificateType::HardwareCertificate : CertificateInformation::CertificateType::SoftwareNextcloudCertificate,
+ _encryptionCertificate.getPrivateKeyData(),
+ QSslCertificate{certificate}};
}
const QSslCertificate& ClientSideEncryption::getCertificate() const
return;
}
- _encryptionCertificate = CertificateInformation{_encryptionCertificate.getPrivateKeyData(), QSslCertificate{readJob->binaryData(), QSsl::Pem}};
+ _encryptionCertificate = CertificateInformation{useTokenBasedEncryption() ? CertificateInformation::CertificateType::HardwareCertificate : CertificateInformation::CertificateType::SoftwareNextcloudCertificate,
+ _encryptionCertificate.getPrivateKeyData(),
+ QSslCertificate{readJob->binaryData(), QSsl::Pem}};
if (_encryptionCertificate.getCertificate().isNull()) {
fetchPublicKeyFromKeyChain(account);
connect(job, &SignPublicKeyApiJob::jsonReceived, job, [this, account, keyPair = std::move(keyPair)](const QJsonDocument& json, const int retCode) {
if (retCode == 200) {
const auto cert = json.object().value("ocs").toObject().value("data").toObject().value("public-key").toString();
- _encryptionCertificate = CertificateInformation{_encryptionCertificate.getPrivateKeyData(), QSslCertificate{cert.toLocal8Bit(), QSsl::Pem}};
+ _encryptionCertificate = CertificateInformation{useTokenBasedEncryption() ? CertificateInformation::CertificateType::HardwareCertificate : CertificateInformation::CertificateType::SoftwareNextcloudCertificate,
+ _encryptionCertificate.getPrivateKeyData(),
+ QSslCertificate{cert.toLocal8Bit(), QSsl::Pem}};
Bio certificateBio;
const auto certificatePem = _encryptionCertificate.getCertificate().toPem();
BIO_write(certificateBio, certificatePem.constData(), certificatePem.size());
connect(job, &JsonApiJob::jsonReceived, [this, account](const QJsonDocument& doc, int retCode) {
if (retCode == 200) {
QString publicKey = doc.object()["ocs"].toObject()["data"].toObject()["public-keys"].toObject()[account->davUser()].toString();
- _encryptionCertificate = CertificateInformation{_encryptionCertificate.getPrivateKeyData(), QSslCertificate{publicKey.toLocal8Bit(), QSsl::Pem}};
+ _encryptionCertificate = CertificateInformation{useTokenBasedEncryption() ? CertificateInformation::CertificateType::HardwareCertificate : CertificateInformation::CertificateType::SoftwareNextcloudCertificate,
+ _encryptionCertificate.getPrivateKeyData(),
+ QSslCertificate{publicKey.toLocal8Bit(), QSsl::Pem}};
fetchAndValidatePublicKeyFromServer(account);
} else if (retCode == 404) {
qCDebug(lcCse()) << "No public key on the server";
CertificateInformation::CertificateInformation(PKCS11_KEY *hardwarePrivateKey,
QSslCertificate &&certificate)
- : _hardwarePrivateKey(hardwarePrivateKey)
- , _certificate(std::move(certificate))
+ : _hardwarePrivateKey{hardwarePrivateKey}
+ , _certificate{std::move(certificate)}
+ , _certificateType{CertificateType::HardwareCertificate}
{
checkEncryptionCertificate();
}
-CertificateInformation::CertificateInformation(const QByteArray &privateKey, QSslCertificate &&certificate)
+CertificateInformation::CertificateInformation(CertificateType certificateType,
+ const QByteArray &privateKey,
+ QSslCertificate &&certificate)
: _hardwarePrivateKey()
, _privateKeyData()
, _certificate(std::move(certificate))
+ , _certificateType{certificateType}
{
if (!privateKey.isEmpty()) {
setPrivateKeyData(privateKey);
}
- checkEncryptionCertificate();
+ switch (_certificateType)
+ {
+ case CertificateType::HardwareCertificate:
+ checkEncryptionCertificate();
+ break;
+ case CertificateType::SoftwareNextcloudCertificate:
+ doNotCheckEncryptionCertificate();
+ break;
+ }
}
bool CertificateInformation::operator==(const CertificateInformation &other) const
}
}
+void CertificateInformation::doNotCheckEncryptionCertificate()
+{
+ _certificateExpired = false;
+ _certificateNotYetValid = false;
+ _certificateRevoked = false;
+ _certificateInvalid = false;
+}
+
}
class CertificateInformation {
public:
+ enum class CertificateType {
+ SoftwareNextcloudCertificate,
+ HardwareCertificate,
+ };
+
CertificateInformation();
explicit CertificateInformation(PKCS11_KEY *hardwarePrivateKey,
QSslCertificate &&certificate);
- explicit CertificateInformation(const QByteArray& privateKey,
+ explicit CertificateInformation(CertificateType certificateType,
+ const QByteArray& privateKey,
QSslCertificate &&certificate);
[[nodiscard]] bool operator==(const CertificateInformation &other) const;
private:
void checkEncryptionCertificate();
+ void doNotCheckEncryptionCertificate();
+
PKCS11_KEY* _hardwarePrivateKey = nullptr;
QByteArray _privateKeyData;
QSslCertificate _certificate;
+ CertificateType _certificateType = CertificateType::SoftwareNextcloudCertificate;
+
bool _certificateExpired = true;
bool _certificateNotYetValid = true;
return initEmptyMetadataLegacy();
}
qCDebug(lcCseMetadata()) << "Setting up empty metadata v2";
+
+ const auto certificateType = _account->e2e()->useTokenBasedEncryption() ?
+ FolderMetadata::CertificateType::HardwareCertificate : FolderMetadata::CertificateType::SoftwareNextcloudCertificate;
+
if (_isRootEncryptedFolder) {
- if (!addUser(_account->davUser(), _account->e2e()->getCertificate())) {
+ if (!addUser(_account->davUser(), _account->e2e()->getCertificate(), certificateType)) {
qCDebug(lcCseMetadata) << "Empty metadata setup failed. Could not add first user.";
_account->reportClientStatus(OCC::ClientStatusReportingStatus::E2EeError_GeneralError);
return;
initMetadata();
}
-bool FolderMetadata::addUser(const QString &userId, const QSslCertificate &certificate)
+bool FolderMetadata::addUser(const QString &userId,
+ const QSslCertificate &certificate,
+ CertificateType certificateType)
{
Q_ASSERT(_isRootEncryptedFolder);
Q_ASSERT(!certificate.isNull());
return false;
}
- const auto shareUserCertificate = CertificateInformation{{}, QSslCertificate{certificate}};
+ auto convertedCertificateType = CertificateInformation::CertificateType::HardwareCertificate;
+ switch (certificateType)
+ {
+ case CertificateType::HardwareCertificate:
+ convertedCertificateType = CertificateInformation::CertificateType::HardwareCertificate;
+ break;
+ case CertificateType::SoftwareNextcloudCertificate:
+ convertedCertificateType = CertificateInformation::CertificateType::SoftwareNextcloudCertificate;
+ break;
+ }
+
+ const auto shareUserCertificate = CertificateInformation{convertedCertificateType, {}, QSslCertificate{certificate}};
if (userId.isEmpty() || certificate.isNull() || !shareUserCertificate.canEncrypt()) {
- qCWarning(lcCseMetadata()) << "Could not add a folder user. Invalid userId or certificate.";
+ qCWarning(lcCseMetadata()) << "Could not add a folder user. Invalid userId or certificate."
+ << userId
+ << (certificate.isNull() ? "user certificate is invalid" : "user certificate is valid")
+ << (shareUserCertificate.canEncrypt() ? "certificate of share receiver user can encrypt" : "certificate of share receiver user cannot encrypt");
return false;
}
};
Q_ENUM(FolderType)
+ enum class CertificateType {
+ SoftwareNextcloudCertificate,
+ HardwareCertificate,
+ };
+ Q_ENUM(CertificateType)
+
FolderMetadata(AccountPtr account, const QString &remoteFolderRoot, FolderType folderType = FolderType::Nested);
/*
* construct metadata based on RootEncryptedFolderInfo
[[nodiscard]] bool moveFromFileDropToFiles();
// adds a user to have access to this folder (always generates new metadata key)
- [[nodiscard]] bool addUser(const QString &userId, const QSslCertificate &certificate);
+ [[nodiscard]] bool addUser(const QString &userId, const QSslCertificate &certificate, CertificateType certificateType);
// removes a user from this folder and removes and generates a new metadata key
[[nodiscard]] bool removeUser(const QString &userId);
return;
}
+ const auto certificateType = _account->e2e()->useTokenBasedEncryption() ?
+ FolderMetadata::CertificateType::HardwareCertificate : FolderMetadata::CertificateType::SoftwareNextcloudCertificate;
+
const auto result = _operation == Operation::Add
- ? _encryptedFolderMetadataHandler->folderMetadata()->addUser(_folderUserId, _folderUserCertificate)
+ ? _encryptedFolderMetadataHandler->folderMetadata()->addUser(_folderUserId, _folderUserCertificate, certificateType)
: _encryptedFolderMetadataHandler->folderMetadata()->removeUser(_folderUserId);
if (!result) {
encryptedFile.initializationVector = EncryptionHelper::generateRandom(16);
metadata->addEncryptedFile(encryptedFile);
- QVERIFY(metadata->addUser(_secondAccount->davUser(), _secondAccount->e2e()->getCertificate()));
+ QVERIFY(metadata->addUser(_secondAccount->davUser(), _secondAccount->e2e()->getCertificate(), FolderMetadata::CertificateType::SoftwareNextcloudCertificate));
QVERIFY(metadata->removeUser(_secondAccount->davUser()));
- QVERIFY(metadata->addUser(_secondAccount->davUser(), _secondAccount->e2e()->getCertificate()));
+ QVERIFY(metadata->addUser(_secondAccount->davUser(), _secondAccount->e2e()->getCertificate(), FolderMetadata::CertificateType::SoftwareNextcloudCertificate));
const auto encryptedMetadata = metadata->encryptedMetadata();
QVERIFY(!encryptedMetadata.isEmpty());